import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

@SuppressWarnings("serial")
public class Main extends JFrame implements ActionListener {
	public static void main(String[] args) {
		try {
			Main frame = new Main();
			frame.setSize(200, 250);
			frame.setPreferredSize(new Dimension(200, 250));
			frame.setResizable(false);
			frame.createGUI();
			frame.setVisible(true);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
	}

	private Container window;
	private GridLayout gridLayout;
	private JLabel labelForOwnIP;
	private JLabel labelForOwnIPVal;
	private JLabel labelForServerIP;
	private JTextField textFieldForServerIP;
	private JLabel labelForServerPort;
	private JTextField textFieldForServerPort;
	private JLabel labelForName;
	private JTextField textFieldForName;
	private JLabel labelForRoom;
	private JComboBox comboForRoom;
	private JButton likeButton;
	private JButton dislikeButton;

	private String ownIP = null;
	private String serverIP = "192.168.2.198";
	private String serverPort = "59876";
	private int serverPortInt = 59876;
	private String name = "NAME";
	private String room = "Weide";
	private DatagramSocket clientSocket = null;

	private void createGUI() throws UnknownHostException {
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		window = this.getContentPane();
		gridLayout = new GridLayout(6, 2);
		window.setLayout(gridLayout);

		labelForOwnIP = new JLabel();
		labelForOwnIP.setText("  Own IP: ");
		window.add(labelForOwnIP);

		ownIP = java.net.InetAddress.getLocalHost().getHostAddress().toString();
		labelForOwnIPVal = new JLabel();
		labelForOwnIPVal.setText(ownIP);
		window.add(labelForOwnIPVal);

		labelForServerIP = new JLabel();
		labelForServerIP.setText("  Server IP: ");
		window.add(labelForServerIP);

		textFieldForServerIP = new JTextField("0.0.0.0");
		textFieldForServerIP.setText(serverIP);
		textFieldForServerIP.addActionListener(this);
		textFieldForServerIP.setActionCommand("serverip");
		window.add(textFieldForServerIP);

		labelForServerPort = new JLabel();
		labelForServerPort.setText("  Server Port: ");
		window.add(labelForServerPort);

		textFieldForServerPort = new JTextField("");
		textFieldForServerPort.setText(serverPort);
		textFieldForServerPort.addActionListener(this);
		textFieldForServerPort.setActionCommand("serverport");
		window.add(textFieldForServerPort);

		labelForName = new JLabel();
		labelForName.setText("  Name: ");
		window.add(labelForName);

		textFieldForName = new JTextField("");
		textFieldForName.setText(name);
		textFieldForName.addActionListener(this);
		textFieldForName.setActionCommand("name");
		window.add(textFieldForName);

		labelForRoom = new JLabel();
		labelForRoom.setText("  Room: ");
		window.add(labelForRoom);

		String[] items = { "Weide", "Camping", "Main Stage", "Marquee",
				"Dance Hall", "Boiler room", "The Shelter", "Club", "Chateau",
				"Wablief" };
		comboForRoom = new JComboBox(items);
		comboForRoom.addActionListener(this);
		comboForRoom.setActionCommand("room");
		comboForRoom.setEnabled(true);
		window.add(comboForRoom);

		likeButton = new JButton("Like");
		likeButton.addActionListener(this);
		likeButton.setActionCommand("like");
		likeButton.setEnabled(true);
		window.add(likeButton);

		dislikeButton = new JButton("Dislike");
		dislikeButton.addActionListener(this);
		dislikeButton.setActionCommand("dislike");
		dislikeButton.setEnabled(true);
		window.add(dislikeButton);

		try {
			clientSocket = new DatagramSocket();
		} catch (SocketException e) {
			e.printStackTrace();
		}
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().compareTo("serverip") == 0)
			setServerIP();
		else if (e.getActionCommand().compareTo("serverport") == 0)
			setServerPort();
		else if (e.getActionCommand().compareTo("name") == 0)
			setName();
		else if (e.getActionCommand().compareTo("room") == 0)
			sendLocationMessage();
		else if (e.getActionCommand().compareTo("like") == 0)
			sendLikeMessage(5.0f);
		else if (e.getActionCommand().compareTo("dislike") == 0)
			sendLikeMessage(0.0f);
	}

	private void sendLikeMessage(float nbStars) {
		try {
			InetAddress IPAddress = InetAddress.getByName(serverIP);

			int cap = 8 + 2 + ownIP.getBytes().length + 2
					+ name.getBytes().length + 4;

			ByteBuffer b = ByteBuffer.allocate(cap);

			// stream ID
			b.putLong(2);
			// IP address
			short s1 = (short) ownIP.getBytes().length;
			b.putShort(s1);
			b.put(ownIP.getBytes());
			// name
			short s2 = (short) name.getBytes().length;
			b.putShort(s2);
			b.put(name.getBytes());
			// The rating
			b.putFloat(nbStars);

			byte[] sendData = b.array();
			DatagramPacket sendPacket = new DatagramPacket(sendData,
					sendData.length, IPAddress, serverPortInt);
			clientSocket.send(sendPacket);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (SocketException e1) {
			e1.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void sendLocationMessage() {
		try {
			InetAddress IPAddress = InetAddress.getByName(serverIP);
			room = (String) comboForRoom.getSelectedItem();

			int cap = 8 + 2 + ownIP.getBytes().length + 2
					+ name.getBytes().length + 2 + room.getBytes().length;

			ByteBuffer b = ByteBuffer.allocate(cap);

			// stream ID
			b.putLong(1);
			// IP address
			short s1 = (short) ownIP.getBytes().length;
			b.putShort(s1);
			b.put(ownIP.getBytes());
			// name
			short s2 = (short) name.getBytes().length;
			b.putShort(s2);
			b.put(name.getBytes());
			// room
			short s3 = (short) room.getBytes().length;
			b.putShort(s3);
			b.put(room.getBytes());

			byte[] sendData = b.array();

			DatagramPacket sendPacket = new DatagramPacket(sendData,
					sendData.length, IPAddress, serverPortInt);
			clientSocket.send(sendPacket);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (SocketException e1) {
			e1.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void setServerIP() {
		serverIP = textFieldForServerIP.getText();
		if (!checkIP(serverIP)) {
			likeButton.setEnabled(false);
			dislikeButton.setEnabled(false);
			comboForRoom.setEnabled(false);
		} else {
			likeButton.setEnabled(true);
			dislikeButton.setEnabled(true);
			comboForRoom.setEnabled(true);
		}
	}

	private void setServerPort() {
		serverPort = textFieldForServerPort.getText();
		if (!convertPort(serverPort)) {
			likeButton.setEnabled(false);
			dislikeButton.setEnabled(false);
			comboForRoom.setEnabled(false);
		} else {
			likeButton.setEnabled(true);
			dislikeButton.setEnabled(true);
			comboForRoom.setEnabled(true);
		}
	}

	private void setName() {
		name = textFieldForName.getText();
		if (!checkName(name)) {
			likeButton.setEnabled(false);
			dislikeButton.setEnabled(false);
			comboForRoom.setEnabled(false);
		} else {
			likeButton.setEnabled(true);
			dislikeButton.setEnabled(true);
			comboForRoom.setEnabled(true);
		}
	}

	private boolean checkIP(String IP) {
		IP = IP.trim();
		String[] parts = IP.split("\\.");
		if (parts.length != 4)
			return false;

		for (String s : parts) {
			try {
				int i = Integer.parseInt(s);
				if (i < 0 || i > 255) {
					return false;
				}
			} catch (NumberFormatException e) {
				return false;
			}
		}
		return true;
	}

	private boolean convertPort(String port) {
		port = port.trim();
		try {
			serverPortInt = Integer.parseInt(port);

			return serverPortInt >= 49152 && serverPortInt <= 65535;
		} catch (NumberFormatException e) {
			return false;
		}
	}

	private boolean checkName(String name) {
		return name.length() >= 2;
	}
}
